/*
	ACPI_tables.h

	contains headers for functions relating to ACPI functionality
	also contains ACPI table information

	Author: Aidan Goddard, 17/5/13
*/

#ifndef ACPI_H_INCLUDED
#define ACPI_H_INCLUDED

#include"kernel_tables.h"

// ACPI non-AML tables
// RSDP
typedef struct ACPI_RSDP ACPI_RSDP;
struct __attribute__((__packed__)) ACPI_RSDP
{
	char		signature[8];
	uint8_t		checksum;
	char		OEM_ID[6];
	uint8_t		revision;
	uint32_t	RSDT_address;

	uint32_t	length;
	uint64_t	XSDT_address;
	uint8_t		xchecksum;
	char		reserved[3];

};

// RSDT
typedef struct ACPI_RSDT ACPI_RSDT;
struct __attribute__((__packed__)) ACPI_RSDT
{
	char		signature[4];
	uint32_t	length;
	uint8_t		revision;
	uint8_t		checksum;
	char		OEM_ID[6];
	char		OEM_table_ID[8];
	uint32_t	OEM_revision;
	uint32_t	creator_ID;
	uint32_t	creator_revision;
};

// MADT (Multiple APIC Descriptor Table)
typedef struct ACPI_MADT ACPI_MADT;
struct __attribute__((__packed__)) ACPI_MADT
{
	// header
	char		signature[4];
	uint32_t	length;
	uint8_t		revision;
	uint8_t		checksum;
	char		OEM_ID[6];
	char		OEM_table_ID[8];
	uint32_t	OEM_revision;
	uint32_t	creator_ID;
	uint32_t	creator_revision;

	// rest of table
	uint32_t	APIC_base;
	uint32_t	flags_PCAT_COMPAT : 1;
	uint32_t	flags_reserved : 31;
};

// MADT entry header
typedef struct ACPI_MADT_HEAD ACPI_MADT_HEAD;
struct __attribute__((__packed__)) ACPI_MADT_HEAD
{
	uint8_t		type;
	uint8_t		length;
};

// MADT APIC structure
typedef struct ACPI_MADT_APIC ACPI_MADT_APIC;
struct __attribute__((__packed__)) ACPI_MADT_APIC
{
	uint8_t		type;
	uint8_t		length;
	uint8_t		ACPI_CPU_ID;
	uint8_t		APIC_ID;
	uint32_t	flags_enabled : 1;
	uint32_t	flags_reserved : 31;
};

// MADT IOAPIC structure
typedef struct ACPI_MADT_IOAPIC ACPI_MADT_IOAPIC;
struct __attribute__((__packed__)) ACPI_MADT_IOAPIC
{
	uint8_t		type;
	uint8_t		length;
	uint8_t		APIC_ID;
	uint8_t		zero;
	uint32_t	address;
	uint32_t	GSI_base;
};

// MADT ISA IRQ redirection
typedef struct ACPI_MADT_IRQ ACPI_MADT_IRQ;
struct __attribute__((__packed__)) ACPI_MADT_IRQ
{
	uint8_t		type;
	uint8_t		length;
	uint8_t		bus;
	uint8_t		source;
	uint32_t	GSI;
	uint16_t	flags_polarity : 2;
	uint16_t	flags_triggermode : 2;
	uint16_t	flags_reserved : 12;
};

// MADT NMI source
typedef struct ACPI_MADT_NMI ACPI_MADT_NMI;
struct __attribute__((__packed__)) ACPI_MADT_NMI
{
	uint8_t		type;
	uint8_t		length;
	uint16_t	flags_polarity : 2;
	uint16_t	flags_triggermode : 2;
	uint16_t	flags_reserved : 12;
	uint32_t	GSI;
};


// MADT local NMI source
typedef struct ACPI_MADT_LNMI ACPI_MADT_LNMI;
struct __attribute__((__packed__)) ACPI_MADT_LNMI
{
	uint8_t		type;
	uint8_t		length;
	uint8_t		ACPI_CPU_ID;
	uint16_t	flags_polarity : 2;
	uint16_t	flags_triggermode : 2;
	uint16_t	flags_reserved : 12;
	uint8_t		LINTn;
};

// FADT (Fixed ACPI Descriptor Table)
typedef struct ACPI_FADT ACPI_FADT;
struct __attribute__((__packed__)) ACPI_FADT
{
	// header
	char		signature[4];
	uint32_t	length;
	uint8_t		revision;
	uint8_t		checksum;
	char		OEM_ID[6];
	char		OEM_table_ID[8];
	uint32_t	OEM_revision;
	uint32_t	creator_ID;
	uint32_t	creator_revision;

	// Physical memory address of the FACS
	uint32_t	FIRMWARE_CTRL;

	// 32bit DSDT address
	uint32_t	DSDT;

	// rest of entries here

};

// DSDT (Differentiated System Descriptor Table)
typedef struct ACPI_DSDT ACPI_DSDT;
struct __attribute__((__packed__)) ACPI_DSDT
{
	// header
	char		signature[4];
	uint32_t	length;
	uint8_t		revision;
	uint8_t		checksum;
	char		OEM_ID[6];
	char		OEM_table_ID[8];
	uint32_t	OEM_revision;
	uint32_t	creator_ID;
	uint32_t	creator_revision;

	// AML starts here

};

// HPET descriptor table
typedef struct ACPI_HPET ACPI_HPET;
struct __attribute__((__packed__)) ACPI_HPET
{
	// header
	char		signature[4];
	uint32_t	length;
	uint8_t		revision;
	uint8_t		checksum;
	char		OEM_ID[6];
	char		OEM_table_ID[8];
	uint32_t	OEM_revision;
	uint32_t	creator_ID;
	uint32_t	creator_revision;

	// HPET stuff
	uint32_t	event_timer_block_ID;
	uint8_t		address_space_ID;
	uint8_t		register_bit_width;
	uint8_t		register_bit_offset;
	uint8_t		reserved;
	uint64_t	base_address;
	uint8_t		HPET_number;
	uint16_t	period_minimum_tick;
	uint8_t		page_protection;

};

// MCFG entry table
typedef struct ACPI_MCFG_ENTRY ACPI_MCFG_ENTRY;
struct __attribute__((__packed__)) ACPI_MCFG_ENTRY
{
	uint64_t config_base_address;
	uint16_t PCI_segment_group_number;
	uint8_t start_PCI_bus_number;
	uint8_t end_PCI_bus_number;
	uint32_t reserved;
};

// MCFG table (PCI-Express configuration area) header
typedef struct ACPI_MCFG ACPI_MCFG;
struct __attribute__((__packed__)) ACPI_MCFG
{
	// header
	char		signature[4];
	uint32_t	length;
	uint8_t		revision;
	uint8_t		checksum;
	char		OEM_ID[6];
	char		OEM_table_ID[8];
	uint32_t	OEM_revision;
	uint32_t	creator_ID;
	uint32_t	creator_revision;

	// MCFG stuff
	uint64_t 	reserved;

	// entries
	ACPI_MCFG_ENTRY entries[256];
};

// ACPI table base fetching functions
ACPI_MADT *ACPIGetMADTBase();
ACPI_FADT *ACPIGetFADTBase();
ACPI_DSDT *ACPIGetDSDTBase();
ACPI_HPET *ACPIGetHPETBase();
ACPI_MCFG *ACPIGetMCFGBase();








#endif
